sed 使用的注意事项
删除命令的注意事项
sed 删除命令能够帮助我们更快的删除待删除的行。
你可以通过指定行号的范围,类似于 1,2 这样的表达式来删除第一行与第二行。
使用行号定址的方法灵活性不够,sed 还提供使用正则表达式匹配的方式来指定待删除的地址。
下面是一个具体的示例:
/{/,/}/d
上面的命令首先匹配包含 ‘{’ 的行,以该行作为第一个删除行,删除 ‘{’ 所在行到 ’}‘ 所在行 之间的所有行(包含边界行)。
如果终止地址没匹配到内容就会导致从起始地址开始之后的所有行都被删除,如果你没有测试就指定了 -i 操作,那么你可能会丢失部分文件的内容。
如果起始地址没有匹配到则不会删除任何行,等同于操作无效。
打印命令的注意事项
为了避免直接使用 -i 造成的问题,我一般都会使用 -n 与 p 命令来查看修改的行,当我确定没有问题之后,我常常直接将 -n 改为 -i 就开始执行,却忘记了删除 p 命令。这样导致的结果是每一个处理行都多输出一次,多了很多重复行。
发现问题后,我使用 sed 的多行模式空间来删除连续重复行,解决了上述问题。
多行模式空间的嵌套使用与匹配
我前几天写了下面的 sed 命令:
/^ *$/{
N
/.*<\/grid>/{
N
s/.*\n//
}
}
首先匹配空行或者只包含一个或多个空格的行,匹配成功后将下一行以 '\n' 与当前行分隔添加到模式空间中,然后对模式空间进行匹配,匹配子串成功则继续将下一行以 '\n' 分隔追加到模式空间中,然后删除前两行。
sed 只替换文件中匹配到的第一个位置
这个问题看上去很简单,实际却可能会让人闷头苦想半天。如何仅仅匹配到的第一个位置?这是问题的关键。
实际上 gnu sed 中的地址匹配就有这样的功能。man sed 找到的相关信息如下:
0,addr2
Start out in "matched first address" state, until addr2 is found. This is similar to 1,addr2, except that if addr2 matches the very first line of input
the 0,addr2 form will be at the end of its range, whereas the 1,addr2 form will still be at the beginning of its range. This works only when addr2 is a
regular expression.
将如下内容保存为文件 Makefile:
MAKE
# Automatically generated by gen-build-mk.sh
ifdef O
ifeq ("$(origin O)", "command line")
$(error "Cannot specify O= as you are already in a build directory")
endif
endif
MAKEFLAGS += --no-print-directory
all:
@$(MAKE) -C ../ O=$(CURDIR)
%::
@$(MAKE) -C ../ O=$(CURDIR) $@
将匹配到的第一个 MAKE 字符串替换为 make 可以使用如下命令:
sed -i '0,/MAKE/ s/MAKE/make/' Makefile
执行上面的命令并检查修改后的 Makefile 文件,输出如下:
[wanglongzheng@localhost x86_64-native-linuxapp-gcc]$ sed -i '0,/MAKE/ s/MAKE/make/' Makefile
[wanglongzheng@localhost x86_64-native-linuxapp-gcc]$ cat Makefile
make
# Automatically generated by gen-build-mk.sh
ifdef O
ifeq ("$(origin O)", "command line")
$(error "Cannot specify O= as you are already in a build directory")
endif
endif
MAKEFLAGS += --no-print-directory
all:
@$(MAKE) -C ../ O=$(CURDIR)
%::
@$(MAKE) -C ../ O=$(CURDIR) $@
可以看到只有第一个 MAKE 被替换为了 make。